// -----------------------------------------------------------------------
//  <copyright file="CreateOrganizationCommand.cs" company="LiuliuSoft">
//      Copyright (c) 2022-2024 DaprPlus. All rights reserved.
//  </copyright>
//  <site>https://dapr.plus</site>
//  <last-editor>郭明锋</last-editor>
//  <last-date>2024/12/10 14:32:37</last-date>
// -----------------------------------------------------------------------

using DaprPlus.Identity.Domain.Entities;

using DaprPlus.Identity.Application.Identity.Organizations.Specs;


namespace DaprPlus.Identity.Application.Identity.Organizations.Commands;

[AuthConfig(typeof(Organization), ResourceAccessType.RoleLimit, "Create")]
public class CreateOrganizationCommand : IRequest<ApiResult>, ICommand
{
    public required OrganizationInDto[] Dtos { get; set; }
}

public class CreateOrganizationCommandHandler(IRepository<Organization> repository)
    : IRequestHandler<CreateOrganizationCommand, ApiResult>
{
    public async Task<ApiResult> Handle(CreateOrganizationCommand request, CancellationToken cancellationToken)
    {
        foreach (var dto in request.Dtos)
        {
            var entity = dto.MapTo<Organization>();
            entity.SetId();

            // 设置树路径
            if (dto.ParentId.HasValue)
            {
                var parent = await repository.FindAsync(dto.ParentId.Value, cancellationToken);
                entity.SetTreePath(parent!.TreePathString);
            }
            else
            {
                entity.SetTreePath(null);
            }

            await repository.InsertAsync(entity, cancellationToken);
        }

        return ApiResult.Success($"组织机构 {request.Dtos.ExpandAndToString(m => m.Name)} 创建成功");
    }
}

public class CreateOrganizationCommandValidator : AbstractValidator<CreateOrganizationCommand>
{
    public CreateOrganizationCommandValidator(IRepository<Organization> repository)
    {
        RuleFor(m => m.Dtos)
            .NotEmpty()
            .WithMessage("组织机构数据不能为空")
            .Must(dtos =>
            {
                var names = dtos.Select(x => x.Name).ToList();
                return names.Count == names.Distinct().Count();
            })
            .WithMessage("批量创建的组织机构中存在重复的名称");

        RuleForEach(m => m.Dtos).ChildRules(dto =>
        {
            dto.RuleFor(m => m.Name)
                .NotEmpty()
                .WithMessage("组织机构名称不能为空")
                .MustAsync(async (dto, name, cancellationToken) =>
                {
                    var spec = new OrganizationByNameAndParentIdSpec(name, dto.ParentId);
                    return !await repository.AnyAsync(spec, cancellationToken);
                })
                .WithMessage(m => $"同级节点下已存在名称为 {m.Name} 的组织机构");

            dto.RuleFor(m => m.Code)
                .NotEmpty()
                .WithMessage("组织机构代码不能为空")
                .MustAsync(async (code, cancellationToken) =>
                {
                    var spec = new OrganizationByCodeSpec(code);
                    return !await repository.AnyAsync(spec, cancellationToken);
                })
                .WithMessage(m => $"组织机构代码 {m.Code} 已存在");

            dto.RuleFor(m => m.ParentId)
                .MustAsync(async (parentId, cancellationToken) =>
                {
                    if (!parentId.HasValue)
                    {
                        return true;
                    }
                    return await repository.AnyAsync(parentId.Value, cancellationToken);
                })
                .WithMessage(m => $"上级组织机构（ID: {m.ParentId}）不存在");
        });
    }
}

